/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
/* X-SPDX-Copyright-Text: (c) Copyright 2008-2020 Xilinx, Inc. */
/****************************************************************************
 * Driver for Solarflare network controllers -
 *          resource management for Xen backend, OpenOnload, etc
 *           (including support for SFE4001 10GBT NIC)
 *
 * This file provides helpers to turn bit shifts into dword shifts and
 * check that the bit fields haven't overflown the dword etc.
 *
 * Copyright 2005-2008: Solarflare Communications Inc,
 *                      9501 Jeronimo Road, Suite 250,
 *                      Irvine, CA 92618, USA
 *
 * Developed and maintained by Solarflare Communications:
 *                      <linux-xen-drivers@solarflare.com>
 *                      <onload-dev@solarflare.com>
 *
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation, incorporated herein by reference.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 ****************************************************************************
 */

#ifndef __CI_EFHW_CHECK_H__
#define __CI_EFHW_CHECK_H__

/*----------------------------------------------------------------------------
 *
 * Helpers to turn bit shifts into dword shifts and check that the bit fields
 * haven't overflown the dword etc. Aim is to preserve consistency with the
 * autogenerated headers - once stable we could hard code.
 *
 *---------------------------------------------------------------------------*/

/* mask constructors */
#define __MASK(WIDTH, T)	((((T)1) << (WIDTH)) - 1)
#define __MASK32(WIDTH)	__MASK((WIDTH), uint32_t)
#define __MASK64(WIDTH)	__MASK((WIDTH), uint64_t)

/* constructors for fields within one DWORD */
#define __DW2(LBN)		((LBN) - 32)
#define __DW3(LBN)		((LBN) - 64)
#define __DW4(LBN)		((LBN) - 96)


/* width for lower portion of field spanning DWORDs */
#define __LW(LBN)		(32 - LBN) /* 0 -> 1 */
#define __LW2(LBN)		(64 - LBN) /* 1 -> 2 */
#define __LW3(LBN)		(96 - LBN) /* 2 -> 3 */


/* checks that the autogenerated headers are consistent with our model */
#define __RANGECHCK(v, WIDTH) \
	EFHW_ASSERT(((uint64_t)(v) & ~(__MASK64((WIDTH)))) == 0)


/* check field width if field within a DWORD */
#define __DWCHCK(F) \
	EFHW_BUILD_ASSERT(((F##_LBN) >= 0)  && (((F##_LBN)+(F##_WIDTH)) <= 32))
#define __DW2CHCK(F) \
	EFHW_BUILD_ASSERT(((F##_LBN) >= 32) && (((F##_LBN)+(F##_WIDTH)) <= 64))
#define __DW3CHCK(F) \
	EFHW_BUILD_ASSERT(((F##_LBN) >= 64) && (((F##_LBN)+(F##_WIDTH)) <= 96))
#define __DW4CHCK(F) \
	EFHW_BUILD_ASSERT(((F##_LBN) >= 96) && (((F##_LBN)+(F##_WIDTH)) <= 128))


/* check field width if field spans a DWORD */
#define __LWCHK(F)	EFHW_BUILD_ASSERT(F##_WIDTH >= __LW(F##_LBN))
#define __LW2CHK(F)	EFHW_BUILD_ASSERT(F##_WIDTH >= __LW2(F##_LBN))
#define __LW3CHK(F)	EFHW_BUILD_ASSERT(F##_WIDTH >= __LW3(F##_LBN))


/* fields in the first qword */
#define __QWCHCK(F) \
	EFHW_BUILD_ASSERT(((F##_LBN) >= 0) && (((F##_LBN)+(F##_WIDTH)) <= 64))

#endif /* __CI_EFHW_CHECK_H__ */
